iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Mobile Development

重新瞭解Android硬體控制系列 第 3

110/07 - 建立自己的 ResultContracts

  • 分享至 

  • xImage
  •  

前面講完官方的14種Contracts,但我們也能建立屬於自己的Contracts,以下範例是實作一個跟ActivityResultContracts.StartActivityForResult()一樣功能的Contracts,差別在於這次傳入的是Bundle,回傳一樣是武器名稱

建立LancerActivityLancerActivityResultContract
MainActivity透過LancerActivityResultContract跳到LancerActivity時會帶姓名
LancerActivity離開頁面後會回傳武器

MainActivity畫面如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    tools:context=".MainActivity">

    <com.google.android.material.button.MaterialButton 
        android:id="@+id/amMbLancer"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:text="跳轉 LancerActivity"
        android:textAllCaps="false"
        app:layout_constraintDimensionRatio="5:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/amMbSaber" />
</androidx.constraintlayout.widget.ConstraintLayout>

LancerActivity畫面如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LancerActivity">

    <com.google.android.material.button.MaterialButton
        android:id="@+id/alMbMain"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="8dp"
        android:text="跳轉 Main 回傳 Gae Bolg"
        android:textAllCaps="false"
        app:layout_constraintDimensionRatio="5:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

跳轉後的程式碼

class LancerActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_lancer)

        val bundle = intent.extras
        val name = bundle?.getString(BaseConstants.NAME)
        val gender = bundle?.getString(BaseConstants.GENDER)

        Log.d("maho", "姓名: $name / 性別:$gender")

        initClickListener()
    }

    private fun initClickListener() {
        alMbMain.setOnClickListener {

            val intent = Intent().apply {
                this.putExtra(BaseConstants.WEAPON, "Gae Bolg")
            }

            setResult(RESULT_OK, intent)
            finish()
        }
    }
}

建立合約Contract類別,名稱為LancerActivityResultContract,需要繼承ActivityResultContract<input, output>,程式碼如下

class LancerActivityResultContract : ActivityResultContract<Bundle, String>() {
    override fun createIntent(context: Context, input: Bundle): Intent {
        return Intent(context, LancerActivity::class.java).apply {
            putExtras(input)
        }
    }

    override fun parseResult(resultCode: Int, intent: Intent?): String {
        val weapon = intent?.getStringExtra(BaseConstants.WEAPON)

        return if (Activity.RESULT_OK == resultCode && null != weapon) {
            weapon
        } else {
            BaseConstants.STRING_EMPTY
        }
    }
}

所以自定義合約Contract很簡單,只要決定好輸入和輸出的型態就好,而且把Result拉出來做成類別後,也比較好找程式碼,不用去Activity

建立好LancerActivityResultContract後,和之前的寫法一樣,去MainActivity,把合約Contract和啟動器Launcher實作出來就好,程式碼如下

val bundle = Bundle()
bundle.putString(BaseConstants.NAME, "CuChulainn")
bundle.putString(BaseConstants.GENDER, "male")

lancerActivityResultContract.launch(bundle)
private val lancerActivityResultContract =
    registerForActivityResult(LancerActivityResultContract()) { weapon ->
        Log.d("maho", "回傳: $weapon")
    }

實際執行程式後的Log

D/maho: 姓名: CuChulainn / 性別:male
D/maho: 回傳: Gae Bolg

程式碼放在feature/createContracts分支
https://github.com/AndyAWD/AndroidSystem/tree/feature/createContracts


上一篇
110/02 - 只有 StartActivityForResult 可以用嗎?
下一篇
110/08 - 檔案要存那裡?
系列文
重新瞭解Android硬體控制14
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言